package com.zmn.oms.third.suning.service.impl;

import com.alibaba.fastjson.JSON;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.channel.product.third.ChannelProductThirdListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.consts.GlobalDict;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderDutyConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.baidumap.LngLatLocation;
import com.zmn.oms.model.dto.order.proxy.CancelOrderDTO;
import com.zmn.oms.model.dto.order.proxy.CreateOrderDTO;
import com.zmn.oms.model.dto.order.proxy.OrderLogDTO;
import com.zmn.oms.model.dto.order.proxy.UpdateOrderDTO;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.orderattachment.OrderAttachment;
import com.zmn.oms.model.entity.remark.OrderRemark;
import com.zmn.oms.model.entity.remark.OrderRemarkDetail;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.orderattachment.OrderAttachmentService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkDetailService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.base.util.CoodinateCovertor;
import com.zmn.oms.third.suning.SuningConsts;
import com.zmn.oms.third.suning.SuningUtil;
import com.zmn.oms.third.suning.api.*;
import com.zmn.oms.third.suning.dto.SuningCreateOrderResponseDTO;
import com.zmn.oms.third.suning.dto.SuningRequestDTO;
import com.zmn.oms.third.suning.dto.SuningSyncResponseDTO;
import com.zmn.oms.third.suning.dto.SuningUpdateOrderResponseDTO;
import com.zmn.oms.third.suning.service.SuningService;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 苏宁渠道对接的接口实现类
 *
 * @author xiewenbing
 * @date  2021/01/05 18:00
 */
@Slf4j
@Service
public class SuningServiceImpl implements SuningService {

    @Autowired
    private ProxyOrderBService proxyOrderBService;

    @Autowired
    private BaiduMapBService baiduMapBService;

    @Autowired
    private ZsOrderWorkQueryBService zsOrderWorkQueryBService;

    @Autowired
    private OrderWorkService orderWorkService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @Autowired
    private OrderAttachmentService orderAttachmentService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private OrderRemarkService orderRemarkService;

    @Autowired
    private OrderRemarkDetailService orderRemarkDetailService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected AreaListRemoteService areaListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelProductThirdListRemoteService channelProductThirdListRemoteService;

    /**
     * 处理渠道发送过来的请求
     *
     * @param requestDTO
     * @return
     */
    @Override
    public String handleOrderRequest(SuningRequestDTO requestDTO) {

        // 判断是否支持对接
        if (!SuningConsts.POWER_ON) {
            return SuningUtil.failedResponse("系统暂不支持该接口");
        }

        if (Objects.isNull(requestDTO)) {
            return SuningUtil.failedResponse("系统错误");
        }

        log.info("【{}】收到请求，【{}】【{}】【{}】【{}】",SuningConsts.CHANNEL_NAME,requestDTO.getApp_key(),
                requestDTO.getMethod(),requestDTO.getSign(),requestDTO.getBody());

        // 参数判断
        if (StringUtil.isBlank(requestDTO.getApp_key()) || StringUtil.isBlank(requestDTO.getMethod()) ||
                StringUtil.isBlank(requestDTO.getBody()) || StringUtil.isBlank(requestDTO.getSign())) {
            return SuningUtil.failedResponse("app_key/method/sign/body 不能为空");
        }

        // 验证签名
        if (!SuningUtil.verifySign(requestDTO)) {
            return SuningUtil.failedResponse("签名验证失败");
        }

        // 请求处理
        switch (requestDTO.getMethod()) {
            case SuningConsts.METHOD_CREATE_ORDER:
                return this.handleCreateOrderRequest(requestDTO.getBody());
            case SuningConsts.METHOD_MODIFY_ORDER:
                return this.handleModifyOrderRequest(requestDTO.getBody());
        }

        return SuningUtil.failedResponse("不支持的服务接口");
    }

    /**
     * 同步订单派单
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderDistribute(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数验证
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException("参数为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        SuningSyncOrderDistributeData syncOrderDistributeData = new SuningSyncOrderDistributeData();
        syncOrderDistributeData.setOrderId(orderWorkLogChange.getOuterId());
        syncOrderDistributeData.setZyry1Bp(SuningConsts.FIELD_MASTER_CODE);
        syncOrderDistributeData.setZyry1BpName(SuningConsts.FIELD_MASTER_NAME);
        syncOrderDistributeData.setZyry1BpTel(SuningConsts.FIELD_MASTER_PHONE);
        syncOrderDistributeData.setLatestAssignmengtTime(DateUtil.getNowFormatted());

        // 预约时间 - 必填，如果没有则填入当前时间
        syncOrderDistributeData.setSrvTime(DateUtil.toString(Optional.ofNullable(orderWork.getDutyTime()).orElse(DateUtil.getNow())));

        String response = SuningUtil.postHttpRequest(SuningConsts.METHOD_ORDER_DISTRIBUTE, JSON.toJSONString(syncOrderDistributeData));
        if (StringUtil.isBlank(response)) {
            throw new OmsBaseException("调用反馈派工信息接口失败");
        }

        // 解析应答数据
        this.parseSyncResponse(response);
    }

    /**
     * 同步订单预约时间
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderDutytime(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数验证
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException("参数为空");
        }

        // 工单查询
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        // 状态查询
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            throw new OmsBaseException("工单未派单，不同预约");
        }

        // 预约状态
        if (Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, orderWork.getDutyStatus())) {
            throw new OmsBaseException("预约状态不为预约成功，不同步");
        }

        // 预约失败
        Date dutyTime = orderWork.getDutyTime();
        if (Objects.isNull(dutyTime)) {
            throw new OmsBaseException("预约时间为空，不同步");
        }

        // 同步数据
        SuningSyncOrderStatusData syncOrderStatusData = new SuningSyncOrderStatusData();
        syncOrderStatusData.setObjectId(orderWorkLogChange.getOuterId());
        syncOrderStatusData.setFromSys(SuningConsts.FIELD_FROM_SYS);
        syncOrderStatusData.setPartnerNo(SuningConsts.FIELD_MASTER_CODE);
        syncOrderStatusData.setUserStatus(SuningConsts.STATUS_CODE_CHANGE_DUTYTIME);
        syncOrderStatusData.setXdsj(DateUtil.getNowFormatted());
        syncOrderStatusData.setReasonDesc("改约");
        syncOrderStatusData.setReasonRemark("改约");
        syncOrderStatusData.setAnotherDate(DateUtil.toString(dutyTime));
        syncOrderStatusData.setSrvMemo(orderWork.getCurrentRemark());

        String response = SuningUtil.postHttpRequest(SuningConsts.METHOD_ORDER_DESTORY, JSON.toJSONString(syncOrderStatusData));
        if (StringUtil.isBlank(response)) {
            throw new OmsBaseException("调用反馈销单（改约）信息接口失败");
        }

        // 解析应答数据
        this.parseSyncResponse(response);
    }

    /**
     * 同步订单完成
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderComplete(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数验证
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException("参数为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        Long orderId = orderWork.getOrderId();
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderId);
        if (Objects.isNull(orderDetail)) {
            throw new OmsBaseException("查找对应的订单详情失败");
        }

        // 完成时间
        Date completeTime = Optional.ofNullable(orderWork.getCompleteTime()).orElse(DateUtil.getNow());

        // 同步数据
        SuningSyncOrderStatusData syncOrderStatusData = new SuningSyncOrderStatusData();
        syncOrderStatusData.setObjectId(orderWorkLogChange.getOuterId());
        syncOrderStatusData.setFromSys(SuningConsts.FIELD_FROM_SYS);
        syncOrderStatusData.setPartnerNo(SuningConsts.FIELD_MASTER_CODE);
        syncOrderStatusData.setUserStatus(SuningConsts.STATUS_CODE_COMPLETE);
        syncOrderStatusData.setXdsj(DateUtil.toString(completeTime));
        syncOrderStatusData.setSrvMemo(orderWork.getCurrentRemark());
        syncOrderStatusData.setSpotWxcs(SuningConsts.FIELD_REPAIR_CODE);
        syncOrderStatusData.setSpotWxcsDec(SuningConsts.FIELD_REPAIR_DESC);
        syncOrderStatusData.setXdAddress(orderDetail.getAddress());
        syncOrderStatusData.setXdzsbs("Y");

        // 经纬度
        double[] lngLat = CoodinateCovertor.bd_decrypt(orderDetail.getLongitude().doubleValue(),orderDetail.getLatitude().doubleValue());
        syncOrderStatusData.setXdjd(String.valueOf(lngLat[0]));
        syncOrderStatusData.setXdwd(String.valueOf(lngLat[1]));

        // 图片
        StringBuilder imageSrc = new StringBuilder();
        // 读取 oms_order_attachment 的工单照片
        List<OrderAttachment> orderAttachments = orderAttachmentService.listAttachmentByOrderId(orderId);
        if (!CollectionUtils.isEmpty(orderAttachments)) {
            for (OrderAttachment orderAttachment : orderAttachments) {
                if (!StringUtil.isNotBlank(orderAttachment.getSrc())) {
                    imageSrc.append(orderAttachment.getSrc()).append(",");
                }
            }
        }
        // 读取 oms_order_extend 的工单照片
        OrderExtend orderExtend = orderExtendService.findMiniOrderExtendByOrderId(orderId);
        if (Objects.nonNull(orderExtend) && !StringUtil.isNotBlank(orderExtend.getImageSrc())) {
            imageSrc.append(orderExtend.getImageSrc());
            syncOrderStatusData.setSign(orderExtend.getMasterSrc());
        }

        syncOrderStatusData.setPic(imageSrc.toString());

        String response = SuningUtil.postHttpRequest(SuningConsts.METHOD_ORDER_DESTORY, JSON.toJSONString(syncOrderStatusData));
        if (StringUtil.isBlank(response)) {
            throw new OmsBaseException("调用反馈销单（完成）信息接口失败");
        }

        // 解析应答数据
        this.parseSyncResponse(response);
    }

    /**
     * 同步订单取消
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderCancel(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数验证
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException("参数不能为null");
        }

        // 判断是否为渠道取消的订单，是则不处理
        if ((orderWorkLogChange.getOperatorId() == Long.valueOf(OrderConsts.CHANNEL_ID_SUNING_BW)) &&
                (orderWorkLogChange.getOperatorType() == GlobalConsts.OPERATE_USER_TYPE_CHANNEL)) {
            throw new OmsBaseException("工单为渠道方取消，无需同步");
        }

        // 订单查找
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        // 判断状态，如果未派单则同步派单接口(假)
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            this.syncOrderDistribute(orderWorkLogChange);
        }

        // 获取取消原因
        Long orderId = orderWorkLogChange.getOrderId();
        Long workId = orderWorkLogChange.getWorkId();
        String cancelReason = "订单被取消";
        OrderRemark orderRemark = orderRemarkService.findByOrderIdAndType(orderId, workId, OrderConsts.ORDER_REMARK_TYPE_CANCEL);
        if (Objects.nonNull(orderRemark)) {
            if (StringUtil.isNotBlank(orderRemark.getContent())) {

                List<OrderRemarkDetail> remarkDetailList = orderRemarkDetailService.listOrderRemarkDetailByRemarkId(orderId, workId,
                        orderRemark.getRemarkId());
                if (!CollectionUtils.isEmpty(remarkDetailList)) {
                    cancelReason = remarkDetailList.get(0).getMapName();
                }
            } else {
                cancelReason = orderRemark.getContent();
            }
        }

        // 同步数据
        SuningSyncOrderStatusData syncOrderStatusData = new SuningSyncOrderStatusData();
        syncOrderStatusData.setObjectId(orderWorkLogChange.getOuterId());
        syncOrderStatusData.setFromSys(SuningConsts.FIELD_FROM_SYS);
        syncOrderStatusData.setPartnerNo(SuningConsts.FIELD_MASTER_CODE);
        syncOrderStatusData.setUserStatus(SuningConsts.STATUS_CODE_CANCEL);
        syncOrderStatusData.setXdsj(DateUtil.getNowFormatted());
        syncOrderStatusData.setReasonDesc(cancelReason);
        syncOrderStatusData.setReasonRemark(cancelReason);
        syncOrderStatusData.setSrvMemo(orderWork.getCurrentRemark());

        String response = SuningUtil.postHttpRequest(SuningConsts.METHOD_ORDER_DESTORY, JSON.toJSONString(syncOrderStatusData));
        if (StringUtil.isBlank(response)) {
            throw new OmsBaseException("调用反馈销单（取消）信息接口失败");
        }

        // 解析应答数据
        this.parseSyncResponse(response);
    }

    /**
     * 同步订单上门
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderVisit(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数验证
        if (Objects.isNull(orderWorkLogChange)) {
            throw new OmsBaseException("参数为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderWorkLogChange.getOrderId(),orderWorkLogChange.getWorkId());
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找对应的订单失败");
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        if (Objects.isNull(orderDetail)) {
            throw new OmsBaseException("查找对应的订单详情失败");
        }

        // 同步数据
        SuningSyncOrderVistSignData syncOrderVistSignData = new SuningSyncOrderVistSignData();
        syncOrderVistSignData.setOrderId(orderWork.getOuterId());
        syncOrderVistSignData.setWorkerBp(SuningConsts.FIELD_MASTER_CODE);
        syncOrderVistSignData.setLatestDoorTime(DateUtil.toString(Optional.ofNullable(orderWork.getVisitTime()).orElse(DateUtil.getNow())));
        syncOrderVistSignData.setSmZsbs("Y");
        syncOrderVistSignData.setSmAddress(orderDetail.getAddress());

        double[] lngLat = CoodinateCovertor.bd_decrypt(orderDetail.getLongitude().doubleValue(),orderDetail.getLatitude().doubleValue());
        syncOrderVistSignData.setSmJd(String.valueOf(lngLat[0]));
        syncOrderVistSignData.setSmWd(String.valueOf(lngLat[1]));

        String response = SuningUtil.postHttpRequest(SuningConsts.METHOD_ORDER_VIST_SIGN, JSON.toJSONString(syncOrderVistSignData));
        if (StringUtil.isBlank(response)) {
            throw new OmsBaseException("调用反馈现场签到信息接口失败");
        }

        // 解析应答数据
        this.parseSyncResponse(response);
    }

    /**
     * 处理订单信息传输数据
     * @param requstBody
     * @return
     */
    protected String handleCreateOrderRequest(String requstBody) {

        SuningCreateOrderData createOrderData;

        // 解析请求数据
        try {
            createOrderData = JSON.parseObject(requstBody, SuningCreateOrderData.class);
        } catch (Exception exception) {
            log.info("【{}】解析创建订单数据异常",SuningConsts.CHANNEL_NAME,requstBody);
            return SuningUtil.failedResponse("数据解析错误");
        }

        if (Objects.isNull(createOrderData)) {
            return SuningUtil.failedResponse("数据解析失败");
        }

        // 通过外部订单id和渠道查找订单
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(createOrderData.getOrderId(),OrderConsts.CHANNEL_ID_SUNING_BW);
        if (Objects.nonNull(zsOrderWorkVO)) {
            return SuningUtil.failedResponse("重复的订单");
        }

        SuningCreateOrderResponseDTO responseDTO = new SuningCreateOrderResponseDTO();
        responseDTO.setOrderId(createOrderData.getOrderId());
        responseDTO.setReturnCode(SuningConsts.RESPONSE_CODE_FAILED);

        // 供应商判断
        if (!Objects.equals(createOrderData.getSupplierCode(), SuningConsts.FIELD_SUPPLIER_CODE)) {
            responseDTO.setReturnMessage("不支持的供应商");
            return JSON.toJSONString(responseDTO);
        }

        // 订单类型判断 - 去掉 2021/02/03
        /****
        if (!Objects.equals(createOrderData.getOrderTypeDesc(), SuningConsts.ACCEPT_ORDER_TYPE)) {
            responseDTO.setReturnMessage("不支持的订单类型");
            return JSON.toJSONString(responseDTO);
        }
         ****/

        // 订单状态判断
        if (!Objects.equals(createOrderData.getStatusCode(), SuningConsts.STATUS_CODE_DISTRIBUTE)) {
            responseDTO.setReturnMessage("不支持的订单状态");
            return JSON.toJSONString(responseDTO);
        }

        log.info("【{}】创建订单【{}】", SuningConsts.CHANNEL_NAME,requstBody);

        Long orderId = 0L;
        try {
            // 生成创建订单数据
            CreateOrderDTO createOrderDTO = buildCreateOrderDTO(createOrderData);

            // 新建订单
            OrderBO orderBO = proxyOrderBService.createOrder(createOrderDTO);
            if (Objects.nonNull(orderBO)) {
                orderId = orderBO.getOrderWork().getOrderId();

                // 订单自动流转
                workFlowContextBService.asyncAutoFlow(orderId, orderBO.getOrderWork().getWorkId());
            }

        } catch (OmsBaseException exception) {
            log.info("【{}】创建订单异常，OmsBaseException【{}】",SuningConsts.CHANNEL_NAME, exception.getMessage());

            responseDTO.setReturnMessage(Optional.ofNullable(exception.getMessage()).orElse("创建订单失败"));
            return JSON.toJSONString(responseDTO);

        } catch (Exception exception) {

            log.info("【{}】 创建订单失异常 Exception【{}】",SuningConsts.CHANNEL_NAME,exception.getMessage());

            responseDTO.setReturnMessage(Optional.ofNullable(exception.getMessage()).orElse("创建订单失败"));
            return JSON.toJSONString(responseDTO);
        }

        log.info("【{}】创建订单成功【{}】", SuningConsts.CHANNEL_NAME,orderId);

        // 成功应答信息
        responseDTO.setReturnCode(SuningConsts.RESPONSE_CODE_SUCCESS);
        responseDTO.setReturnMessage("success");
        return JSON.toJSONString(responseDTO);
    }

    /**
     * 生成创建订单的数据
     * @param createOrderData
     * @return
     * @throws OmsBaseException
     */
    protected CreateOrderDTO buildCreateOrderDTO(SuningCreateOrderData createOrderData) throws OmsBaseException {

        // 参数检验
        if (StringUtil.isBlank(createOrderData.getOrderId())) {
            throw new OmsBaseException("服务订单号为空");
        }

        String userPhone = Optional.ofNullable(createOrderData.getMobPhone()).orElse(createOrderData.getPhoneNum());
        if (StringUtil.isBlank(userPhone)) {
            throw new OmsBaseException("联系人电话为空");
        }

        String userAddress = SuningUtil.parseAddress(createOrderData.getSrvAddress());
        if (StringUtil.isBlank(userAddress)) {
            throw new OmsBaseException("联系人地址为空");
        }

        // 订单创建数据
        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        // 输入类型
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        // 渠道id
        createOrderDTO.setChannelId(OrderConsts.CHANNEL_ID_SUNING_BW);

        // 外部订单id - 母单号
        createOrderDTO.setOuterId(createOrderData.getOrderId());

        // 联系人
        createOrderDTO.setContactName(createOrderData.getConsignee());

        // 联系人电话
        createOrderDTO.setTelephone(userPhone);

        // 性别
        createOrderDTO.setGender(GlobalDict.GENDER_NO);

        // 预约时间
        Long dutyTime = Long.valueOf(createOrderData.getSrvTime());
        if (Objects.nonNull(dutyTime)) {
            createOrderDTO.setDutyTime(DateUtil.parse(dutyTime));
        }

        // 地址
        createOrderDTO.setAddress(userAddress);

        // 厂商单
        createOrderDTO.setFactory(GlobalConsts.NO);

        // 备注
        createOrderDTO.setRemark(createOrderData.getSrvMemo());

        // 业务类型
        createOrderDTO.setBizType(GlobalConsts.BIZ_TYPE_C);

        // 平台
        createOrderDTO.setPlat(GlobalConsts.PLAT_MARK_ZMN);

        // 禁止弃单
        createOrderDTO.setDisableDiscard(GlobalConsts.YES);

        // 操作人
        createOrderDTO.setOperator("系统");

        // 操作人id
        createOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        // 操作者类型
        createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        // 预付
        createOrderDTO.setChannelPrepayAmount(SuningConsts.getServiceProductPrepay(createOrderData.getSrvcmmdtyCode()));
        createOrderDTO.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
        createOrderDTO.setDisableDiscard(GlobalConsts.NO);

        // 城市id
        Integer cityId = 500100;
        do {
            // 详细地址获取经纬度
            LngLatLocation areaLocation = baiduMapBService.location(userAddress);
            if (Objects.isNull(areaLocation)) {
                log.info("【{}】地址信息解析失败",SuningConsts.CHANNEL_NAME);
                break;
            }

            createOrderDTO.setLatitude(Double.valueOf(areaLocation.getLat()));
            createOrderDTO.setLongitude(Double.valueOf(areaLocation.getLng()));

            // 经纬度查找区域信息
            ResponseDTO<AreaDRO> areaDROByLatAndLng = areaListRemoteService.getAreaByLatAndLng(Double.valueOf(areaLocation.getLng()), Double.valueOf(areaLocation.getLat()));
            if (Objects.isNull(areaDROByLatAndLng) || Objects.isNull(areaDROByLatAndLng.getData())) {
                log.info("【{}】根据经纬度查找地址信息失败",SuningConsts.CHANNEL_NAME);
                break;
            }

            cityId = areaDROByLatAndLng.getData().getParentId();

            // 再设一次经纬度
            Double longitude = Double.valueOf(areaDROByLatAndLng.getData().getLongitude());
            Double latitude = Double.valueOf(areaDROByLatAndLng.getData().getLatitude());
            createOrderDTO.setLongitude(longitude);
            createOrderDTO.setLatitude(latitude);

        } while (false);

        createOrderDTO.setCityId(cityId);

        // 产品
        List<OrderProductDTO> orderProductList =  new LinkedList<>();
        OrderProductDTO orderProductDTO = new OrderProductDTO();

        // 查找产品id
        ResponseDTO<List<ProductBaseDRO>> productListResponseDTO = channelProductThirdListRemoteService.listByChannelIdAndProductParentIdAndSubId(OrderConsts.CHANNEL_ID_SUNING_BW,
                createOrderData.getSrvcmmdtyCode(), null);
        log.info("【{}】 #ChannelProductMapListRemoteService#查找产品id，入参【{}】 出参【{}】",
                SuningConsts.CHANNEL_NAME, createOrderData.getSrvcmmdtyCode(), productListResponseDTO.toString());

        if (!productListResponseDTO.isSuccess() || Objects.isNull(productListResponseDTO.getData()) || productListResponseDTO.getData().isEmpty()) {
            orderProductDTO.setProductId(SuningConsts.getProductId(createOrderData.getSrvcmmdtyCode()));
        } else {
            orderProductDTO.setProductId(productListResponseDTO.getData().get(0).getProductId());
        }

        orderProductDTO.setNumber(1);
        orderProductList.add(orderProductDTO);
        createOrderDTO.setOrderProductList(orderProductList);

        // 日志记录
        StringBuilder sbOperateLog = new StringBuilder();
        sbOperateLog.append("<br/> 公司名称：").append(createOrderData.getCompanyName()).
                append("<br/> 服务备注：").append(createOrderData.getSrvMemo()).
                append("<br/> 服务商品：").append(SuningConsts.getServiceProductName(createOrderData.getSrvcmmdtyCode())).
                append("<br/> 创建时间：").append(DateUtil.toString(Long.valueOf(createOrderData.getCreateTime()))).
                append("<br/> 订单类型：").append(createOrderData.getOrderTypeDesc()).
                append("<br/>");

        createOrderDTO.setOperatorLogRemark(sbOperateLog.toString());

        // 扩展数据
        SuningOrderExtendData orderOuterDataDTO = BeanMapper.map(createOrderData,SuningOrderExtendData.class);
        if (Objects.nonNull(orderOuterDataDTO)) {
            createOrderDTO.setOuterData(JSON.toJSONString(orderOuterDataDTO));
        }

        return createOrderDTO;
    }

    /**
     * 处理订单信息修改数据
     * @param requstBody
     * @return
     */
    protected String handleModifyOrderRequest(String requstBody) {

        SuningUpdateOrderData updateOrderData;

        // 解析请求数据
        try {
            updateOrderData = JSON.parseObject(requstBody, SuningUpdateOrderData.class);
        } catch (Exception exception) {
            log.info("【{}】解析创建订单数据异常",SuningConsts.CHANNEL_NAME,requstBody);
            return SuningUtil.failedResponse("数据解析错误");
        }

        if (Objects.isNull(updateOrderData)) {
            return SuningUtil.failedResponse("数据解析失败");
        }

        // 通过外部订单id和渠道查找订单
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(updateOrderData.getServiceNum(),OrderConsts.CHANNEL_ID_SUNING_BW);
        if (Objects.isNull(zsOrderWorkVO)) {
            return SuningUtil.failedResponse("订单不存在");
        }

        SuningUpdateOrderResponseDTO responseDTO = new SuningUpdateOrderResponseDTO();
        responseDTO.setServiceNum(updateOrderData.getServiceNum());

        try {
            switch (updateOrderData.getOperationType()) {
                case SuningConsts.UPDATE_OPERATE_TYPE_CHANGE:
                    this.handleUpdateOrder(zsOrderWorkVO,updateOrderData);
                    break;
                case SuningConsts.UPDATE_OPERATE_TYPE_CANCEL:
                    this.handleCancelOrder(zsOrderWorkVO,updateOrderData);
                    break;
                default:
                    throw new OmsBaseException("不支持的操作类型");
            }
        } catch (OmsBaseException exception) {

            responseDTO.setReturnCode(SuningConsts.RESPONSE_CODE_FAILED);
            responseDTO.setReturnMessage(Optional.ofNullable(exception.getMessage()).orElse("处理订单信息失败"));
            return JSON.toJSONString(responseDTO);
        }

        // 成功应答信息
        responseDTO.setReturnCode(SuningConsts.RESPONSE_CODE_SUCCESS);
        responseDTO.setReturnMessage("success");
        return JSON.toJSONString(responseDTO);
    }

    /**
     * 修改订单的预约时间/用户姓名/地址/联系电话等
     *
     * @param zsOrderWorkVO
     * @param updateOrderData
     */
    protected void handleUpdateOrder(ZsOrderWorkVO zsOrderWorkVO, SuningUpdateOrderData updateOrderData) throws OmsBaseException {

        // 用户手机、地址、以及预约时间
        String userPhone = updateOrderData.getMobPhone();
        String userAddress = SuningUtil.parseAddress(updateOrderData.getSrvAddress());
        Date dutyTime = null;
        if (StringUtil.isNotBlank(updateOrderData.getSrvTime())) {
            dutyTime = DateUtil.parse(Long.valueOf(updateOrderData.getSrvTime()));
        }

        // 更新数据
        UpdateOrderDTO updateOrderDTO = new UpdateOrderDTO();
        updateOrderDTO.setOrderId(zsOrderWorkVO.getOrderId());
        StringBuilder sbUpdateLog = new StringBuilder();

        if (!Objects.equals(userPhone,zsOrderWorkVO.getUserPhone())) {
            sbUpdateLog.append("电话：").append(zsOrderWorkVO.getUserPhone()).append("修改为 ").append(userPhone).append("</br>");
            updateOrderDTO.setPhone(userPhone);
        }

        if (!Objects.equals(userAddress,zsOrderWorkVO.getUserAddress())) {
            sbUpdateLog.append("地址：").append(zsOrderWorkVO.getUserAddress()).append("修改为 ").append(userAddress).append("</br>");
            updateOrderDTO.setAddress(userAddress);
        }

        if (!Objects.equals(dutyTime,zsOrderWorkVO.getDutyTime())) {
            sbUpdateLog.append("预约时间：");
            if (Objects.nonNull(zsOrderWorkVO.getDutyTime())) {
                sbUpdateLog.append(DateUtil.toString(zsOrderWorkVO.getDutyTime())).append(" ");
            }

            sbUpdateLog.append("修改为 ").append(DateUtil.toString(dutyTime)).append("</br>");
            updateOrderDTO.setDutyTime(dutyTime);
        }

        // 更新判断
        if (StringUtil.isBlank(sbUpdateLog.toString())) {
            log.info("【{}】信息未修改，无需更新",SuningConsts.CHANNEL_NAME);
            return;
        }

        updateOrderDTO.setPhone(userPhone);

        try {
            proxyOrderBService.updateOrder(updateOrderDTO);
        } catch (OmsBaseException exception) {
            log.info("【{}】更新订单异常，【{}】【{}】【{}】,异常【{}】",SuningConsts.CHANNEL_NAME, userPhone, userAddress, dutyTime,exception.getMessage());
            throw new OmsBaseException("订单信息更新失败");
        }

        // 增加日志
        this.addLog(zsOrderWorkVO.getOrderId(),zsOrderWorkVO.getOuterId(),sbUpdateLog.toString());
    }

    /**
     * 取消订单
     *
     * @param zsOrderWorkVO
     * @param updateOrderData
     */
    protected void handleCancelOrder(ZsOrderWorkVO zsOrderWorkVO, SuningUpdateOrderData updateOrderData) throws OmsBaseException {

        // 取消订单数据构建
        CancelOrderDTO cancelDTO = new CancelOrderDTO();
        cancelDTO.setOrderId(zsOrderWorkVO.getOrderId());
        cancelDTO.setOuterId(zsOrderWorkVO.getOuterId());
        cancelDTO.setChannelId(OrderConsts.CHANNEL_ID_SUNING_BW);
        cancelDTO.setOperatorId(Long.valueOf(OrderConsts.CHANNEL_ID_SUNING_BW));
        cancelDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        cancelDTO.setRemark(Optional.ofNullable(updateOrderData.getOrderChangeReason()).orElse("渠道方取消"));

        // 取消订单
        try {
            proxyOrderBService.cancelOrder(cancelDTO);
        } catch (OmsBaseException omsBaseException) {

            log.error("【{}】取消订单失败 消息:[{}]",SuningConsts.CHANNEL_NAME, omsBaseException.getMessage());
            throw new OmsBaseException(Optional.ofNullable(omsBaseException.getMessage()).orElse("订单取消失败"));
        }
    }

    /**
     * 增加操作日志
     *
     * @param orderId
     * @param outerId
     * @param logRemark
     */
    protected void addLog(Long orderId, String outerId, String logRemark) throws OmsBaseException {

        // 构造参数
        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderId);
        orderLogDTO.setOuterId(outerId);
        orderLogDTO.setChannelId(OrderConsts.CHANNEL_ID_SUNING_BW);
        orderLogDTO.setOperatorId((long)OrderConsts.CHANNEL_ID_SUNING_BW);
        orderLogDTO.setOperatorType(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        orderLogDTO.setOperatorLogRemark(logRemark);

        proxyOrderBService.addOrderLog(orderLogDTO);
    }

    /**
     * 解析返回数据
     *
     * @param response
     */
    protected void parseSyncResponse(String response) throws OmsBaseException {

        // 解析返回数据
        SuningSyncResponseDTO syncResponseDTO = null;

        try {
            syncResponseDTO = JSON.parseObject(response,SuningSyncResponseDTO.class);
        } catch (Exception exception) {
            throw new OmsBaseException("解析返回数据异常");
        }

        StringBuilder sbMsg = new StringBuilder();

        if (Objects.isNull(syncResponseDTO)) {
            throw new OmsBaseException("解析返回数据失败");
        }

        // 判断是否接受失败
        if (!syncResponseDTO.getSuccess()) {
            sbMsg.append("返回数据表示API接受失败");
            if (StringUtil.isNotBlank(syncResponseDTO.getMessage())) {
                sbMsg.append(" - ").append(syncResponseDTO.getMessage());
            }
            throw new OmsBaseException(sbMsg.toString());
        }

        if (StringUtil.isBlank(syncResponseDTO.getData())) {
            return;
        }

        // 解析报文内容
        SuningSyncResponseData responseData = null;
        try {
            responseData = JSON.parseObject(syncResponseDTO.getData(),SuningSyncResponseData.class);
        } catch (Exception exception) {
            throw new OmsBaseException("解析返回数据的报文内容异常");
        }

        if (Objects.isNull(responseData)) {
            throw new OmsBaseException("解析返回数据的报文内容失败");
        }

        // 判断是否成功
        if (Objects.equals(SuningConsts.SYNC_RESPONSE_CODE_SUCCESS, responseData.getReturnCode())) {
            return;
        }

        sbMsg.append("返回数据的报文表示反馈订单信息失败");
        if (StringUtil.isNotBlank(responseData.getMessage())) {
            sbMsg.append(" - ").append(responseData.getMessage());
        }

        throw new OmsBaseException(sbMsg.toString());
    }
}
